//
//  PDFTools.m
//  CGPDFTest
//
//  Created by Emo, on 2024/5/16.
//

#import "PDFTools.h"

/**
 //设置文档标题 可选设置
 const CFStringRef  kCGPDFContextTitle;
 //设置文档的作者 可选设置
 const CFStringRef  kCGPDFContextAuthor;
 //设置文档的副标题 可选设置
 const CFStringRef  kCGPDFContextSubject;
 //为文档设置关键字 可选设置 可以设置为一个数组 设置多个关键字
 const CFStringRef  kCGPDFContextKeywords;
 //设置文档的创建者
 const CFStringRef  kCGPDFContextCreator;
 //为文档设置所有者密码
 const CFStringRef  kCGPDFContextOwnerPassword;
 //为文档设置用户密码
 const CFStringRef  kCGPDFContextUserPassword;
 //设置加密密钥长度
 const CFStringRef  kCGPDFContextEncryptionKeyLength;
 //设置是否允许绘制
 const CFStringRef  kCGPDFContextAllowsPrinting;
 //设置是否允许复制
 const CFStringRef  kCGPDFContextAllowsCopying;
 */

@implementation PDFTools



/// 将多张图片合成为PDF文件
/// - Parameters:
///   - dataSource: 图片数据源
///   - pdfSize: pdf大小
///   - pwd: 密码
///   - filePath: 生成pdf的路径
+ (void)creatPDFWithImagesDataSource:(NSArray <UIImage *>*)dataSource pdfSize:(CGSize)pdfSize pdfPWD:(NSString *)pwd filePath:(NSString *)filePath {
    // 将OC字符串转成C字符串
    CFStringRef pwdStrRef = NULL;
    if (pwd && pwd.length > 0) {
        pwdStrRef = (__bridge_retained CFStringRef)pwd;
    }
    CFStringRef filePathStrRef = NULL;
    if (filePath && filePath.length > 0) {
        filePathStrRef = (__bridge_retained CFStringRef)filePath;
    }
    
    // 获取PDF单页尺寸
    if (CGSizeEqualToSize(pdfSize, CGSizeZero)) {
        pdfSize = CGSizeMake(595, 842);
    }
    CGRect pdfRect = (CGRect){CGPointZero, pdfSize};
    
    // 创建本地存储PDF路径url
    CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, filePathStrRef, kCFURLPOSIXPathStyle, NO);
    
    // 创建pdf信息字典
    CFMutableDictionaryRef pdfInfo = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    // 设置pdf标题
    CFDictionarySetValue(pdfInfo, kCGPDFContextTitle, CFSTR(""));
    // 设置作者
    CFDictionarySetValue(pdfInfo, kCGPDFContextAuthor, CFSTR("Emo,"));
    // 设置是否允许绘制
    CFDictionarySetValue(pdfInfo, kCGPDFContextAllowsPrinting, kCFBooleanTrue);
    // 设置密码
    if (pwdStrRef) {
        CFDictionarySetValue(pdfInfo, kCGPDFContextOwnerPassword, pwdStrRef);
        CFDictionarySetValue(pdfInfo, kCGPDFContextUserPassword, pwdStrRef);
    }
    
    // 转换rect为data
    CFDataRef rectDataRef = CFDataCreate(NULL, (const UInt8 *)&pdfRect, sizeof(pdfRect));
    // 创建单页信息
    CFMutableDictionaryRef pageInfo = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(pageInfo, kCGPDFContextMediaBox, rectDataRef);
    
    // 创建PDF上下文
    CGContextRef context = CGPDFContextCreateWithURL(urlRef, &pdfRect, pdfInfo);
    if (context == NULL) {
        NSLog(@"create pdf context fail.");
        if (pwdStrRef) {
            CFRelease(pwdStrRef);
        }
        CFRelease(filePathStrRef);
        CFRelease(urlRef);
        CFRelease(pdfInfo);
        CFRelease(pageInfo);
        CFRelease(rectDataRef);
        CGContextRelease(context);
        return;
    }
    
    // 循环创建PDF页面
    for (int i = 0; i < dataSource.count; i++) {
        UIImage *image = dataSource[i];
        // 等比计算图片尺寸
        CGFloat imgW = image.size.width;
        CGFloat imgH = image.size.height;
        CGFloat pdfW = pdfRect.size.width;
        CGFloat pdfH = pdfRect.size.height;
        CGRect pageRect = [self calculatePDFPageRectWithImgW:imgW imgH:imgH pdfW:pdfW pdfH:pdfH];
        
        // 将UIImage转成NSData
        NSData *imageData = UIImageJPEGRepresentation(image, 0.1);
        // 将NSData转成CFData
        CFDataRef imgDataRef = (__bridge_retained CFDataRef)imageData;
        // 开始绘制PDF单页
        CGPDFContextBeginPage(context, pageInfo);
        
        // 绘制PDF单页
        CGDataProviderRef providerRef = CGDataProviderCreateWithCFData(imgDataRef);
        CGImageRef imageRef = CGImageCreateWithJPEGDataProvider(providerRef, NULL, NO, kCGRenderingIntentDefault);
        CGContextDrawImage(context, pageRect, imageRef);
        // 绘制完成释放资源
        CGDataProviderRelease(providerRef);
        CGImageRelease(imageRef);
        CFRelease(imgDataRef);
        
        // 结束绘制PDF单页
        CGPDFContextEndPage(context);
    }
    
    // 释放资源
    if (pwdStrRef) {
        CFRelease(pwdStrRef);
    }
    CFRelease(filePathStrRef);
    CFRelease(urlRef);
    CFRelease(pdfInfo);
    CFRelease(pageInfo);
    CFRelease(rectDataRef);
    CGContextRelease(context);
}

// 计算图片在PDF的位置
+ (CGRect)calculatePDFPageRectWithImgW:(CGFloat)imgW imgH:(CGFloat)imgH pdfW:(CGFloat)pdfW pdfH:(CGFloat)pdfH {
    CGFloat w = imgW;
    CGFloat h = imgH;
    // 宽度超出，则设置最大宽度，再等比计算高度
    if (imgW > pdfW) {
        w = pdfW;
        h = w * imgH / imgW;
    }
    // 等比计算后的高度超出，设置最大高度，再等比计算宽度
    if (h > pdfH) {
        h = pdfH;
        w = h * imgW / imgH;
    }
    // 计算图片在PDF页中的x坐标
    CGFloat x = 0;
    if (pdfW != w) {
        x = (pdfW - w) / 2;
    }
    // 计算图片在PDF页中的y坐标
    CGFloat y = 0;
    if (pdfH != h) {
        y = (pdfH - h) / 2;
    }
    CGRect pageRect = CGRectMake(x, y, w, h);
    return pageRect;
}


+ (NSString *)localFilePath:(NSString *)fileName {
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    path = [path stringByAppendingPathComponent:fileName];
    return path;
}

@end
